﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System.Collections.Generic;
using Microsoft.VisualStudio.TestTools.UnitTesting;

using System;
using System.Linq;
using ScrumTable.Common.Collections;
using ScrumTable.Common.Monitoring;
using ScrumTable.Common.Security;
using ScrumTable.DL.Data.Common;
using ScrumTable.DL.Data.Excel.Config.Driver;
using ScrumTable.DL.Data.Excel.Config.Schema;
using ScrumTable.DL.Data.Generic.Test.Mocks;

#endregion

namespace ScrumTable.DL.Data.Excel.Test
{
    /// <summary>
    /// This is the test class for Local.DataAccessObject class.
    /// </summary>
    [TestClass]
    public class DataAccessObjectTest
    {
        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------

        private DataContext _context;

        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext { get; set; }

        #endregion

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        /// <summary>
        /// Creates a new DataAccessObjectTest instance.
        /// </summary>
        public DataAccessObjectTest()
        {
        }

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        /// <summary>
        /// Use TestInitialize to run code before running each test .
        /// </summary>
        [TestInitialize]
        public void TestInitialize()
        {
            _context = new DataContext(new DataContextInfoStub(
                TestContext.TestDir,
                dci => new DataSchemaSelector(dci),
                dci => new DriverConfigSelector(dci)));
            _context.Connection.Connect(
                new ConnectionInformationManager(ConnectionInformation.Empty),
                result => { },
                Resources.GetProjectTestDataFilePath(TestContext.TestDir) );

            _context.ImportData(Resources.FullProject1IdChain, new NullDataImportMonitor());
        }

        /// <summary>
        /// Use TestCleanup to run code after each test has run.
        /// </summary>
        [TestCleanup]
        public void TestCleanup()
        {
            _context.Dispose();
            _context = null;
        }

        [TestMethod]
        public void TestGetAll()
        {
            TestGetAll(Resources.IterationCount, _context.Schema.IterationSchema);
            TestGetAll(Resources.MemberCount, _context.Schema.MemberSchema);
            TestGetAll(Resources.ProjectCount, _context.Schema.ProjectSchema);
            TestGetAll(Resources.TaskCount, _context.Schema.TaskSchema);
            TestGetAll(Resources.UserStoryCount, _context.Schema.UserStorySchema);
            TestGetAll(Resources.BugCount, _context.Schema.BugSchema);
            TestGetAll(Resources.TypeCount, _context.Schema.TypeSchema);
            TestGetAll(Resources.TransitionCount, _context.Schema.TransitionSchema);
            TestGetAll(Resources.AttachmentCount, _context.Schema.AttachmentSchema);
            TestGetAll(Resources.ReportCount, _context.Schema.ReportSchema);
        }

        [TestMethod]
        public void TestGetAllByParent()
        {
            // test mapped hierarchy levels
            Assert.AreEqual(1, _context.Storage[_context.Schema.ProjectSchema].GetAll(ValueChain<string>.Empty).Count);

            Assert.AreEqual(3, _context.Storage[_context.Schema.IterationSchema].GetAll(Resources.Iteration1IdChain).Count);
            Assert.AreEqual(3, _context.Storage[_context.Schema.IterationSchema].GetAll(Resources.Iteration2IdChain).Count);
            Assert.AreEqual(3, _context.Storage[_context.Schema.IterationSchema].GetAll(Resources.Iteration3IdChain).Count);

            Assert.AreEqual(1, _context.Storage[_context.Schema.UserStorySchema].GetAll(Resources.UserStory1IdChain).Count);
            Assert.AreEqual(2, _context.Storage[_context.Schema.UserStorySchema].GetAll(Resources.UserStory2IdChain).Count);
            Assert.AreEqual(1, _context.Storage[_context.Schema.UserStorySchema].GetAll(Resources.UserStory3IdChain).Count);
            Assert.AreEqual(2, _context.Storage[_context.Schema.UserStorySchema].GetAll(Resources.UserStory4IdChain).Count);

            Assert.AreEqual(2, _context.Storage[_context.Schema.MemberSchema].GetAll(Resources.Member1IdChain).Count);
            Assert.AreEqual(2, _context.Storage[_context.Schema.MemberSchema].GetAll(Resources.Member2IdChain).Count);

            Assert.AreEqual(2, _context.Storage[_context.Schema.TaskSchema].GetAll(Resources.Task1IdChain).Count);
            Assert.AreEqual(1, _context.Storage[_context.Schema.TaskSchema].GetAll(Resources.Task2IdChain).Count);
            Assert.AreEqual(2, _context.Storage[_context.Schema.TaskSchema].GetAll(Resources.Task3IdChain).Count);

            Assert.AreEqual(2, _context.Storage[_context.Schema.BugSchema].GetAll(Resources.Bug1IdChain).Count);
            Assert.AreEqual(2, _context.Storage[_context.Schema.BugSchema].GetAll(Resources.Bug2IdChain).Count);
            Assert.AreEqual(1, _context.Storage[_context.Schema.BugSchema].GetAll(Resources.Bug3IdChain).Count);

            Assert.AreEqual(2, _context.Storage[_context.Schema.AttachmentSchema].GetAll(Resources.Attachment1IdChain).Count);
            Assert.AreEqual(1, _context.Storage[_context.Schema.AttachmentSchema].GetAll(Resources.Attachment2IdChain).Count);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void TestGetAllWithException()
        {
            _context.Storage[_context.Schema.ProjectSchema].GetAll(null);
        }

        [TestMethod]
        public void TestGetProjectsById()
        {
            Assert.IsNotNull(_context.Storage[_context.Schema.ProjectSchema].GetById(ValueChain<string>.Empty, Resources.Project1Id));
        }

        [TestMethod]
        public void TestGetIterationsById()
        {
            Assert.IsNotNull(_context.Storage[_context.Schema.IterationSchema].GetById(Resources.Iteration1IdChain, Resources.Iteration1Id));
            Assert.IsNotNull(_context.Storage[_context.Schema.IterationSchema].GetById(Resources.Iteration2IdChain, Resources.Iteration2Id));
            Assert.IsNotNull(_context.Storage[_context.Schema.IterationSchema].GetById(Resources.Iteration3IdChain, Resources.Iteration3Id));
        }

        [TestMethod]
        public void TestGetMembersById()
        {
            Assert.IsNotNull(_context.Storage[_context.Schema.MemberSchema].GetById(Resources.Member1IdChain, Resources.Member1Id));
            Assert.IsNotNull(_context.Storage[_context.Schema.MemberSchema].GetById(Resources.Member2IdChain, Resources.Member2Id));
        }

        [TestMethod]
        public void TestGetUserStoriesById()
        {
            Assert.IsNotNull(_context.Storage[_context.Schema.UserStorySchema].GetById(Resources.UserStory1IdChain, Resources.UserStory1Id));
            Assert.IsNotNull(_context.Storage[_context.Schema.UserStorySchema].GetById(Resources.UserStory2IdChain, Resources.UserStory2Id));
            Assert.IsNotNull(_context.Storage[_context.Schema.UserStorySchema].GetById(Resources.UserStory3IdChain, Resources.UserStory3Id));
            Assert.IsNotNull(_context.Storage[_context.Schema.UserStorySchema].GetById(Resources.UserStory4IdChain, Resources.UserStory4Id));
        }

        [TestMethod]
        public void TestGetTasksById()
        {
            Assert.IsNotNull(_context.Storage[_context.Schema.TaskSchema].GetById(Resources.Task1IdChain, Resources.Task1Id));
            Assert.IsNotNull(_context.Storage[_context.Schema.TaskSchema].GetById(Resources.Task2IdChain, Resources.Task2Id));
            Assert.IsNotNull(_context.Storage[_context.Schema.TaskSchema].GetById(Resources.Task3IdChain, Resources.Task3Id));
        }

        [TestMethod]
        public void TestGetBugsById()
        {
            Assert.IsNotNull(_context.Storage[_context.Schema.BugSchema].GetById(Resources.Bug1IdChain, Resources.Bug1Id));
            Assert.IsNotNull(_context.Storage[_context.Schema.BugSchema].GetById(Resources.Bug2IdChain, Resources.Bug2Id));
            Assert.IsNotNull(_context.Storage[_context.Schema.BugSchema].GetById(Resources.Bug3IdChain, Resources.Bug3Id));
        }

        [TestMethod]
        public void TestGetTypesAndMetaById()
        {
            ICollection<IDataObject> childEntries = _context.Storage[_context.Schema.TypeSchema].GetAll(Resources.FullProject1IdChain);
            Assert.AreEqual(3, childEntries.Count);

            foreach (var childEntry in childEntries)
            {
                var metaEntries = _context.Storage[_context.Schema.MetaSchema].GetAll(
                    Resources.FullProject1IdChain.Combine(childEntry.Id));

                Assert.IsTrue(metaEntries.Count() > 0);
            }
        }

        private void TestGetAll(int expectedCount, string schema)
        {
            Assert.AreEqual(
                expectedCount,
                _context.Storage[schema].GetAll().Sum(entry => entry.Value.Count()));
        }

        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------

        #endregion
    }
}
